package com.googlecode.gwtbb.server.intermediate.search;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.store.Directory;

import java.io.IOException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * @author Abraham Grief
 * @version $Id$
 * @since Jul 29, 2008
 */
public class DirectorySearcher {
	private static Log log = LogFactory.getLog(DirectorySearcher.class);
	private Searcher searcher;
	private IndexReader indexReader;
	private Directory directory;
	private Analyzer analyzer;
	private int reopenInitialDelayMillis = 60000;
	private int reopenDelayMillis = 60000;
	private ScheduledExecutorService reopenExecutor;
	private ScheduledFuture reopenFuture;

	public Analyzer getAnalyzer() {
		return analyzer;
	}

	public void setAnalyzer(Analyzer analyzer) {
		this.analyzer = analyzer;
	}

	public Directory getDirectory() {
		return directory;
	}

	public void setDirectory(Directory directory) {
		this.directory = directory;
	}

	public int getReopenDelayMillis() {
		return reopenDelayMillis;
	}

	public void setReopenDelayMillis(int reopenDelayMillis) {
		this.reopenDelayMillis = reopenDelayMillis;
	}

	public ScheduledExecutorService getReopenExecutor() {
		return reopenExecutor;
	}

	public void setReopenExecutor(ScheduledExecutorService reopenExecutor) {
		this.reopenExecutor = reopenExecutor;
	}

	public int getReopenInitialDelayMillis() {
		return reopenInitialDelayMillis;
	}

	public void setReopenInitialDelayMillis(int reopenInitialDelayMillis) {
		this.reopenInitialDelayMillis = reopenInitialDelayMillis;
	}

	public Searcher getSearcher() {
		return searcher;
	}

	public synchronized void destroy() throws IOException {
		reopenFuture.cancel(true);
		searcher.close();
		indexReader.close();
	}

	public synchronized void init() throws IOException {
		indexReader = IndexReader.open(directory);
		searcher = new IndexSearcher(indexReader);

		reopenFuture = reopenExecutor.scheduleWithFixedDelay(new Runnable() {
			public void run() {
				try {
					IndexReader newReader = indexReader.reopen();
					if (newReader != indexReader) {
						Searcher newSearcher = new IndexSearcher(newReader);
						Searcher oldSearcher = searcher;
						IndexReader oldReader = indexReader;
						synchronized (DirectorySearcher.this) {
							searcher = newSearcher;
							indexReader = newReader;
						}
						oldSearcher.close();
						oldReader.close();
					}
				} catch (IOException e) {
					log.error("could not reopen indexReader", e);
				}
			}
		}, reopenInitialDelayMillis, reopenDelayMillis, TimeUnit.MILLISECONDS);
	}
}
